/**
  ******************************************************************************
  * @文件     bsp.c
  * @作者     hero_cao
  * @版本     V1.0.0
  * @日期     2020/07/17
  * @概要     系统初始化、IO初始化、时钟初始化
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stdio.h"
#include "./board/bsp.h"
#include "at32f403a_407_clock.h"


/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
typedef const struct {
    gpio_type       		*port;      //IO 端口
    crm_periph_clock_type	clk;        //IO 时钟
    uint16_t        		pin;        //IO 引脚
    uint8_t         		state;      //IO 输入输出状态 0)推挽输出 1)浮空输入 2)上拉输入 3)下拉输入 4)开漏输出
    uint8_t         		id;         //IO id号
}PORT_INFO_t;

static PORT_INFO_t m_PortInfo[] = {
    {GPIOE, CRM_GPIOE_PERIPH_CLOCK,  GPIO_PINS_3,   0,  eLED_1},
    {GPIOE, CRM_GPIOE_PERIPH_CLOCK,  GPIO_PINS_4,   0,  eLED_2},
	{GPIOC, CRM_GPIOC_PERIPH_CLOCK,  GPIO_PINS_0,   0,  eBEEP},
	{GPIOD, CRM_GPIOD_PERIPH_CLOCK,  GPIO_PINS_12,  0,  eLCD_BK},
	{GPIOC, CRM_GPIOC_PERIPH_CLOCK,  GPIO_PINS_2,   2,  eKEY_A},
	{GPIOC, CRM_GPIOC_PERIPH_CLOCK,  GPIO_PINS_1,   2,  eKEY_B},
	{GPIOA, CRM_GPIOA_PERIPH_CLOCK,  GPIO_PINS_0,   3,  eKEY_S},
	{GPIOD, CRM_GPIOD_PERIPH_CLOCK,  GPIO_PINS_6,   2,  eKEY_U},
	{GPIOE, CRM_GPIOE_PERIPH_CLOCK,  GPIO_PINS_1,   2,  eKEY_D},
	{GPIOE, CRM_GPIOE_PERIPH_CLOCK,  GPIO_PINS_2,   2,  eKEY_L},
	{GPIOE, CRM_GPIOE_PERIPH_CLOCK,  GPIO_PINS_0,   2,  eKEY_R},
	{GPIOC, CRM_GPIOC_PERIPH_CLOCK,  GPIO_PINS_4,   2,  eKEY_AA},
	{GPIOC, CRM_GPIOC_PERIPH_CLOCK,  GPIO_PINS_3,   2,  eKEY_BB},	
};

static uc16 m_PortCount = BSP_CONEOF(m_PortInfo);
static __IO float fac_us;
static __IO float fac_ms;


/**
  * @brief  GPIO初始化设置
  * @param  无
  * @retval 无
  */
void GPIO_Configuration(void)
{
    gpio_init_type gpio_init_struct;
    PORT_INFO_t *pPort = m_PortInfo;
    uint8_t i = 0;

    for (i = 0; i < m_PortCount; i++, pPort++)
    {
		crm_periph_clock_enable(pPort->clk, TRUE);
		gpio_default_para_init(&gpio_init_struct);
		gpio_init_struct.gpio_pins = pPort->pin;
		gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        
        if (pPort->state == 0) {
			gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
			gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
		} else if (pPort->state == 1) {
			gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
			gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
		} else if (pPort->state == 2) {
			gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
			gpio_init_struct.gpio_pull = GPIO_PULL_UP;
		} else if (pPort->state == 3) {
			gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
			gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
		} else if (pPort->state == 4) {
			gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
			gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
		}
            
        gpio_init(pPort->port, &gpio_init_struct);
    }
}

/**
  * @brief  DWT系统定时器时间配置
  * @param  无
  * @retval 无
  */
void DWT_Delay_init()
{
	/* 使能DWT外设 */
    DEM_CR |= (uint32_t)DEM_CR_TRCENA;

    /* DWT CYCCNT寄存器计数清0 */
    DWT_CYCCNT = (uint32_t)0u;

    /* 使能Cortex-M DWT CYCCNT寄存器 */
    DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
}

/**
  * @brief  延时函数
  * @param  nus-延时时间us
  * @retval 无
  */
void Delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t told,tnow,tcnt=0;

    /* 在函数内部初始化时间戳寄存器， */
#if (CPU_TS_INIT_IN_DELAY_FUNCTION)
    /* 初始化时间戳并清零 */
    CPU_TS_TmrInit();
#endif

    ticks = nus * (system_core_clock / 1000000);	/* 需要的节拍数 */
    tcnt = 0;
    told = (uint32_t)DWT_CYCCNT;         			/* 刚进入时的计数器值 */

    while (1) {
        tnow = (uint32_t)DWT_CYCCNT;
        if (tnow != told) {
            /* 32位计数器是递增计数器 */
            if (tnow > told) {
                tcnt += tnow - told;
            } else {
                tcnt += UINT32_MAX - told + tnow;
            }

            told = tnow;

            /*时间超过/等于要延迟的时间,则退出 */
            if (tcnt >= ticks) break;
        }
    }
}

/**
  * @brief  延时函数
  * @param  nms-延时时间ms
  * @retval 无
  */
void Delay_ms(uint16_t nms)
{
    Delay_us(nms * 1000);
}

/**
  * @brief  中断向量，优先级
  * @param  无
  * @retval 无
  */
void NVIC_Configuration(void)
{
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);//优先级设置  全为抢占式优先级
}

/* support printf function, usemicrolib is unnecessary */
#if (__ARMCC_VERSION > 6000000)
  __asm (".global __use_no_semihosting\n\t");
  void _sys_exit(int x)
  {
    x = x;
  }
  /* __use_no_semihosting was requested, but _ttywrch was */
  void _ttywrch(int ch)
  {
    ch = ch;
  }
  FILE __stdout;
#else
 #ifdef __CC_ARM
  #pragma import(__use_no_semihosting)
  struct __FILE
  {
    int handle;
  };
  FILE __stdout;
  void _sys_exit(int x)
  {
    x = x;
  }
  /* __use_no_semihosting was requested, but _ttywrch was */
  void _ttywrch(int ch)
  {
    ch = ch;
  }
 #endif
#endif

#if defined (__GNUC__) && !defined (__clang__)
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

/**
  * @brief  retargets the c library printf function to the usart.
  * @param  none
  * @retval none
  */
PUTCHAR_PROTOTYPE
{
  while(usart_flag_get(USART1, USART_TDBE_FLAG) == RESET);
  usart_data_transmit(USART1, ch);
  return ch;
}

/**
  * @brief  initialize uart
  * @param  baudrate: uart baudrate
  * @retval none
  */
void uart_print_init(uint32_t baudrate)
{
  gpio_init_type gpio_init_struct;

  /* enable the uart and gpio clock */
  crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

  gpio_default_para_init(&gpio_init_struct);

  /* configure the uart tx pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_9;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOA, &gpio_init_struct);

  /* configure uart param */
  usart_init(USART1, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
  usart_transmitter_enable(USART1, TRUE);
  usart_enable(USART1, TRUE);
}

/**
  * @brief  系统初始化
  * @param  无
  * @retval 无
  */
void BSP_Init(void)
{
	system_clock_config();
    NVIC_Configuration();
    GPIO_Configuration();
    DWT_Delay_init();
	uart_print_init(115200);
}

/**
  * @brief  IO 置高
  * @param  n-IO编号
  * @retval 无
  */
void BSP_GpioSet(int n)
{
    if (n < 0) return;
    if (n >= eGPIO_MAX_COUNT) return;
    
    m_PortInfo[n].port->scr = m_PortInfo[n].pin;
}

/**
  * @brief  IO 置低
  * @param  n-IO编号
  * @retval 无
  */
void BSP_GpioReset(int n)
{
    if (n < 0) return;
    if (n >= eGPIO_MAX_COUNT) return;
    
    m_PortInfo[n].port->clr = m_PortInfo[n].pin;
}

/**
  * @brief  IO 电平翻转
  * @param  n-IO编号
  * @retval 无
  */
void BSP_GpioToggle(int n)
{
    if (n < 0) return;
    if (n >= eGPIO_MAX_COUNT) return;
    
    m_PortInfo[n].port->odt ^= m_PortInfo[n].pin;
}

/**
  * @brief  读GPIO
  * @param  n-IO编号
  * @retval 错误返回 -1
  */
int BSP_GpioRead(int n)
{
    if (n < 0) return -1;
    if (n >= eGPIO_MAX_COUNT) return -1;

    return gpio_input_data_bit_read(m_PortInfo[n].port, m_PortInfo[n].pin);
}


/* FILE END */
